/* 
 * File:   SparseMatrixGenerator.h
 * Author: Hugo Bruno
 *
 * Created on November 7, 2013, 5:53 PM
 */

#include "matrix.h"
#include <random>
#include <iostream>
#include <chrono>

#ifndef SPARSEMATRIXGENERATOR_H
#define	SPARSEMATRIXGENERATOR_H

using namespace std;

template <class T>
class SparseMatrixGenerator
{
    public:
        
        SparseMatrixGenerator<T>(T lower_limit, T upper_limit):uniform_distribution(lower_limit,upper_limit){
            unsigned seed = chrono::system_clock::now().time_since_epoch().count();
            generator.seed(seed);
            
        }
        
        Matrix<T> generateBandMatrix(const int m_dim, const int offset);
        Matrix<T> generateRandomMatrix(const int m_dim, const double density = 1 );
        Matrix<T> generateRandomBandMatrix(const int m_dim,const int offset ,const double density);
        Vector<T> generateRandomVector(const int m_dim);
        
       
    private:
       default_random_engine generator;
       uniform_real_distribution<double> uniform_distribution;
       }
;

template <class T>
Matrix<T> SparseMatrixGenerator<T>::generateRandomMatrix(const int m_dim, const double density){
    bernoulli_distribution distribution((density*m_dim*m_dim-m_dim)/((m_dim*m_dim - m_dim)));
    Matrix<T> matrix(m_dim,m_dim);
    matrix.zero();
    for(int i=0; i<m_dim; i++){
        for(int j=0; j<i; j++){
            if(distribution(generator)){
                matrix(i,j) = uniform_distribution(generator);
                matrix(j,i) = matrix(i,j);
            }
        }
        matrix(i,i) = 100;
    }
    return matrix;
}

template <class T>
Matrix<T> SparseMatrixGenerator<T>::generateRandomBandMatrix(const int m_dim, const int offset, const double density){
    bernoulli_distribution distribution(density);
    Matrix<T> matrix(m_dim,m_dim);
    matrix.zero();
    for(int i=0; i<m_dim; i++){
        int j=i-1;
        while(j>=i-offset && j>=0){
            if(distribution(generator)){
            matrix(i,j)=uniform_distribution(generator);
            matrix(j,i)=matrix(i,j);
            }
            j--;
        }        
        matrix(i,i)=100;
}
    
    return matrix;
}

template <class T>
Matrix<T> SparseMatrixGenerator<T>::generateBandMatrix(const int m_dim, const int offset){
    Matrix<T> matrix(m_dim,m_dim);
    matrix.zero();
    for(int i=0; i<m_dim; i++){
        int j=i-1;
        while(j>=i-offset && j>=0){
            matrix(i,j)=uniform_distribution(generator);
            matrix(j,i)=matrix(i,j);
            j--;
        }        
        matrix(i,i)=uniform_distribution(generator);;
}
    
    return matrix;
}

template <class T>
Vector<T> SparseMatrixGenerator<T>::generateRandomVector(const int m_dim){
    Vector<T> vector(m_dim);
    for(int i=0; i<m_dim; i++){
       vector(i) = uniform_distribution(generator);
}
    
    return vector;
    
}


#endif	/* SPARSEMATRIXGENERATOR_H */

